{*******************************************************************************
* The contents of this file are used with permission, subject to the Mozilla   *
* Public License Version 1.1 (the "License"); you may not use this file except *
* in compliance with the License. You may obtain a copy of the License at      *
* http://www.mozilla.org/MPL/                                                  *
*                                                                              *
* Software distributed under the License is distributed on an "AS IS" basis,   *
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for *
* the specific language governing rights and limitations under the License.    *
*                                                                              *
* The Original Code is distributed as part of the "mediate" product and is     *
* Copyright (C) @home media limited. All Rights Reserved.                      *
*                                                                              *
* Email: support@athomemedia.co.uk                                             *
* Web:   http://www.athomemedia.co.uk                                          *
*******************************************************************************}

unit Tray;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ShellAPI, Menus, StdCtrls, Remotes, ImgList, AppEvnts, ExtCtrls;

const
  ENABLED_CAPTION = 'Disable remote control in mediate';
  DISABLED_CAPTION = 'Enable remote control in mediate';
  REG_REMOTE_TYPE = 'remote control type';
  REG_REMOTE_SZ = 'streamzap';
  REG_REMOTE_MCE = 'mce';
  IMAGE_IDX_IDLE = 0;
  IMAGE_IDX_IRCMD = 1;
  IMAGE_IDX_DISABLE = 2;
  POPUP_WIDTH = 220;

type
  TAHMRemoteType = (rtStreamzap, rtMCEIR);

  TAHMMainForm = class(TForm)
    PopupMenu: TPopupMenu;
    miEnabled: TMenuItem;
    miReset: TMenuItem;
    N2: TMenuItem;
    miAbout: TMenuItem;
    N1: TMenuItem;
    miExit: TMenuItem;
    ilTrayIcons: TImageList;
    ApplicationEvents1: TApplicationEvents;
    UseWindowsMCEremotecontrol1: TMenuItem;
    miMCEIR: TMenuItem;
    miStreamzap: TMenuItem;
    TrayIcon: TTrayIcon;
    N3: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure miExitClick(Sender: TObject);
    procedure miEnabledClick(Sender: TObject);
    procedure miResetClick(Sender: TObject);
    procedure miAboutClick(Sender: TObject);
    procedure ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
    procedure miRemoteTypeClick(Sender: TObject);
  private
    { Private declarations }
    FRemote: TAHMRemote;
    FRemoteType: TAHMRemoteType;
    FChanged: Boolean;
    function CheckDLLReady: Boolean;
  protected
    procedure LoadConfiguration;
    procedure SaveConfiguration;
    procedure InitialiseRemote;
    procedure ConfigureEnabledMenu;
  public
    { Public declarations }
    procedure AnimateIcon;
  end;

var
  AHMMainForm: TAHMMainForm;

implementation
{$R *.dfm}

uses Math, About, Messaging, Utilities, RegHelper, Streamzap, MCEIR;

//-----------------------------------------------------------------------------
//----------------------------- Form Events -----------------------------------
//-----------------------------------------------------------------------------

procedure TAHMMainForm.FormCreate(Sender: TObject);
begin
  // Determine whether we've been asked to shutdown helper or not - depends
  // on being passed a SHUTDOWN parameter on command line as first param
  if (ParamCount > 0) and (Pos('SHUTDOWN', UpperCase(ParamStr(1))) > 0) then
  begin
    // Yes, broadcast our custom shutdown message to all other instances & exit
    MessengerInstance.RequestHelperShutdown;
    Application.Terminate;
  end;

  // Load configuration and determine appropriate remote type
  LoadConfiguration;
  InitialiseRemote;
end;

procedure TAHMMainForm.FormDestroy(Sender: TObject);
begin
  // Free our remote helper class
  FRemote.Free;

  // Save configuration if it's changed
  SaveConfiguration;
end;

//-----------------------------------------------------------------------------
//----------------------------- Menu Events -----------------------------------
//-----------------------------------------------------------------------------

procedure TAHMMainForm.miEnabledClick(Sender: TObject);
begin
  // Toggle enable/disable our little remote helper
  if CheckDLLReady then
    FRemote.Enabled := not FRemote.Enabled;

  // Ensure enabled menu item is in a consistent state
  ConfigureEnabledMenu;
end;

procedure TAHMMainForm.miResetClick(Sender: TObject);
begin
  // Reset remote helper DLL
  if CheckDLLReady then
    FRemote.Reset;

  // Ensure enabled menu item is in a consistent state
  ConfigureEnabledMenu;
end;

procedure TAHMMainForm.miRemoteTypeClick(Sender: TObject);
var
  NewType: TAHMRemoteType;
begin
  // Determine new remote type
  NewType := TAHMRemoteType(TMenuItem(Sender).Tag);
  if NewType <> FRemoteType then
  begin
    // It's a different type - reinitialise remote
    FChanged := True;
    FRemoteType := NewType;
    InitialiseRemote;
  end;
end;

procedure TAHMMainForm.miAboutClick(Sender: TObject);
begin
  // Show information about our little remote helper app
  TfrmAbout.ShowAboutBox;
end;

procedure TAHMMainForm.miExitClick(Sender: TObject);
begin
  // Quit our little tray application
  Application.Terminate;
end;

//-----------------------------------------------------------------------------
//-------------------------- Application Events -------------------------------
//-----------------------------------------------------------------------------

procedure TAHMMainForm.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin
  // If we receive shutdown message from another instance then exit
  if MessengerInstance.HandleMessage(Msg, Handled) = mtHelperShutdown then
    Application.Terminate;
end;

//-----------------------------------------------------------------------------
//-------------------- Miscellaneous Support Methods --------------------------
//-----------------------------------------------------------------------------

procedure TAHMMainForm.LoadConfiguration;
begin
  try
    with TAHMRegistryHelper.Create do
    try
      if ReadStrValue(REG_REMOTE_TYPE) = REG_REMOTE_MCE then
        FRemoteType := rtMCEIR
      else
        FRemoteType := rtStreamzap; // default if not defined
    finally
      Free;
    end;
  except
    // Ignore any registry permission errors
  end;

  // Clear configuration changed flag
  FChanged := False;
end;

procedure TAHMMainForm.SaveConfiguration;
begin
  // Only save if configuration has changed
  if FChanged then
    try
      with TAHMRegistryHelper.Create do
      try
        case FRemoteType of
          rtMCEIR:     WriteStrValue(REG_REMOTE_TYPE, REG_REMOTE_MCE);
          rtStreamzap: WriteStrValue(REG_REMOTE_TYPE, REG_REMOTE_SZ);
        end;
      finally
        Free;
      end;
  except
    // Ignore any registry permission errors
  end;

  // Clear configuration changed flag
  FChanged := False;
end;

procedure TAHMMainForm.InitialiseRemote;
begin
  // Release old remote helper instance
  FreeAndNil(FRemote);

  // Create appropriate instance of remote helper
  if FRemoteType = rtMCEIR then FRemote := TAHMRemoteMCEIR.Create
  else FRemote := TAHMRemoteStreamzap.Create;

  // Enable our remote helper instance if ready
  if FRemote.Ready then
    FRemote.Enabled := True;

  // Ensure enabled menu item is in a consistent state
  ConfigureEnabledMenu;

  // Ensure appropriate remote type is ticked in submenu
  miStreamzap.Checked := (FRemoteType = rtStreamzap);
  miMCEIR.Checked := (FRemoteType = rtMCEIR);
end;

function TAHMMainForm.CheckDLLReady: Boolean;
begin
  // Set default result - not available
  Result := False;

  // Allow looping whilst Streamzap is not yet ready
  if FRemote is TAHMRemoteStreamzap then
    while not FRemote.Ready do
    begin
      if MessageDlg('mediate helper failed to initialise Streamzap remote control.' +
                    sLineBreak + sLineBreak +
                    'Please check that the "Streamzap Remote" tray application is ' +
                    'running - you may need to expand the tray area to see all icons. ' +
                    'If this is running but is showing "(Not Available)" then you may ' +
                    'wish to try removing and then re-inserting the USB IR Receiver, or ' +
                    'restarting Windows.' + sLineBreak + sLineBreak +
                    'If you continue to experience problems then please visit the ' +
                    'support section on our website for further advice.', mtInformation,
                    [mbRetry, mbOk], 0) <> mrRetry then Exit;
    end;

  // Hurrah - it's ready now...
  Result := True;
end;

//-----------------------------------------------------------------------------
//--------------------- User Interface Configuration --------------------------
//-----------------------------------------------------------------------------

procedure TAHMMainForm.ConfigureEnabledMenu;
begin
  // Display suitable caption for enable menu item
  if FRemote.Enabled then miEnabled.Caption := ENABLED_CAPTION
                     else miEnabled.Caption := DISABLED_CAPTION;

  // Choose appropriate tray caption for enabled/disabled state
  if FRemote.Enabled then
    TrayIcon.Hint := Application.Title
  else
    TrayIcon.Hint := Application.Title + ' (disabled)';

  // Choose appropriate tray icon for enabled/disabled state
  if FRemote.Enabled then TrayIcon.IconIndex := IMAGE_IDX_IDLE
                     else TrayIcon.IconIndex := IMAGE_IDX_DISABLE;
end;

procedure TAHMMainForm.AnimateIcon;
begin
  // Briefly flash led on tray icon when we receive a remote command
  TrayIcon.IconIndex := IMAGE_IDX_IRCMD;
  Sleep(50);
  TrayIcon.IconIndex := IMAGE_IDX_IDLE;
end;



end.
